﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace SimpleConfig
{
    /// <summary>
    /// SimpleConf main class. Manages a config.xml file with multitype properties stored and grouped by sections.
    /// Version 1.0
    /// August 2011
    /// Author: M. Gomez (manolo@kodesoft.net) 
    /// </summary>
    public class SimpleConf
    {
        #region Constants
        /// <summary>
        /// Default config filename
        /// </summary>
        private const String _DEFAULT_CONFIG_FILE_NAME = "config.xml";
        /// <summary>
        /// Default xpath initial segment to find the target section <section name=""></section>  
        /// </summary>
        private const String _DEFAULT_XPATH_TO_SECTION = "/configuration/section[@name=\"";
        /// <summary>
        /// Default xpath subsegment to find the target property <property name=""></property>
        /// </summary>
        private const String _DEFAULT_SUB_XPATH_TO_PROPERTY = "\"]/property[@name=\"";
        /// <summary>
        /// Default xpath segment to end the complete xpath
        /// </summary>
        private const String _DEFAULT_SUB_XPATH_PROPERTY_END = "\"]";
        #endregion
        #region class properties
        /// <summary>
        /// config.xml file path
        /// </summary>
        protected String configFilePath;
        public String ConfigFilePath;
        /// <summary>
        /// XmlDocument handler
        /// </summary>
        private XmlDocument docHandler = null;
        #endregion
        /// <summary>
        /// Class constructor
        /// </summary>
        /// <param name="configFilePath">Config filename</param>
        #region methods
        public SimpleConf(String configFilePath = _DEFAULT_CONFIG_FILE_NAME)
        {
            this.configFilePath = configFilePath;
            this.openConfigHandler(configFilePath);
        }

        /// <summary>
        /// Open the config file handler and initializes the process
        /// </summary>
        /// <param name="configFilePath">Config filename</param>
        /// <returns>Boolean with the result of the operation</returns>
        public Boolean openConfigHandler(String configFilePath) {
            Boolean retVal = false;
            try
            {
                docHandler = new XmlDocument();
                docHandler.Load(this.configFilePath);
                retVal = true;
            }
            catch (Exception ex)
            {
                retVal = false;
            }
            return retVal;
        }

        /// <summary>
        /// Reads a string property value
        /// </summary>
        /// <param name="property">Property name</param>
        /// <param name="section">Section name where property is stored</param>
        /// <returns>Stringized property value</returns>
        public String readString(String property, String section = "general") {
            try
            {
                String var = (docHandler.SelectSingleNode(String.Concat(_DEFAULT_XPATH_TO_SECTION,
                                                section,
                                                _DEFAULT_SUB_XPATH_TO_PROPERTY,
                                                property,
                                                _DEFAULT_SUB_XPATH_PROPERTY_END))).InnerText;
                return  var ?? "";
            }
            catch (Exception ex) {
                return "";
            }
        }

        /// <summary>
        /// Write a property value as a string
        /// </summary>
        /// <param name="value">Value to set to the property</param>
        /// <param name="property">Property name</param>
        /// <param name="section">Section name where property is stored</param>
        /// <returns>Stringized property value</returns>
        public Boolean writeString(String value, String property, String section = "general") {
            try
            {
                XmlNode n;
                n = docHandler.SelectSingleNode(String.Concat(_DEFAULT_XPATH_TO_SECTION,
                                                section,
                                                _DEFAULT_SUB_XPATH_TO_PROPERTY,
                                                property,
                                                _DEFAULT_SUB_XPATH_PROPERTY_END));
                n.InnerText = value;
                docHandler.Save(this.configFilePath);
                return true;
            }
            catch (Exception ex){
                return false;
            }    
           
        }

        /// <summary>
        /// Reads a property value as an integer
        /// </summary>
        /// <param name="property">Property name</param>
        /// <param name="section">Section name where property is stored</param>
        /// <returns>Integer value of the property or -1 if error while reading</returns>
        public int readInteger(String property, String section = "general")
        {
            try
            {
                return Int32.Parse(this.readString(property, section));
            }
            catch (Exception ex) {
                return -1;
            }
        }

        /// <summary>
        /// Writes a property value as an integer
        /// </summary>
        /// <param name="value">Value to set to the property</param>
        /// <param name="property">Property name</param>
        /// <param name="section">Section name where property is stored</param>
        /// <returns>Boolean result of the operation</returns>
        public Boolean writeInteger(Int32 value, String property, String section = "general")
        {
            return this.writeString(value.ToString(), property, section);
        }

        /// <summary>
        /// Reads a property value as a boolean
        /// </summary>
        /// <param name="property">Property name</param>
        /// <param name="section">Section name where property is stored</param>
        /// <returns>Boolean value of the property</returns>
        public Boolean readBoolean(String property, String section = "general")
        {
            return Boolean.Parse(this.readString(property, section));
        }

        /// <summary>
        /// Writes a property value as a boolean
        /// </summary>
        /// <param name="value">Value to set to the property</param>
        /// <param name="property">Property name</param>
        /// <param name="section">Section name where property is stored</param>
        /// <returns>Boolean result of the operation</returns>
        public Boolean writeBoolean(Boolean value, String property, String section = "general")
        {
            return this.writeString(value.ToString(), property, section);
        }

        /// <summary>
        /// Saves the current state of the config object to the config file
        /// </summary>
        public void saveConfig() {
            docHandler.Save(this.configFilePath);
        }
        #endregion
    }
}
